package com.zs.toolbox.web2j.system.core.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qq.connect.javabeans.qzone.UserInfoBean;
import com.zs.toolbox.web2j.common.exception.WtExceptions;
import com.zs.toolbox.web2j.common.response.WtBaseResponse;
import com.zs.toolbox.web2j.system.core.config.qq.QQOAuth;
import com.zs.toolbox.web2j.system.core.entity.WtUserOpenEntity;
import com.zs.toolbox.web2j.system.core.mapper.user.WtUserOpenMapper;
import com.zs.toolbox.web2j.system.core.response.WtOpenUserLoginResponse;
import com.zs.toolbox.web2j.system.core.service.WtUserOpenService;
import com.zs.toolbox.web2j.system.core.service.WtUserService;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.result.WxMpUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;

/**
 * <p>
 * 用户-第三方登陆信息 服务实现类
 * </p>
 *
 * @author eric.zhang
 * @since 2018-10-08
 */
@Service
@Slf4j
public class WtUserOpenServiceImpl extends ServiceImpl<WtUserOpenMapper, WtUserOpenEntity> implements WtUserOpenService {
    @Autowired
    private WxMpService wxService;

    @Autowired
    private WtUserService wtUserService;

    static final String OPEN_TYPE_WECHAT = "wechat";
    static final String OPEN_TYPE_QQ = "qq";

    @Autowired
    QQOAuth qqoAuth;



    @Override
    public WtUserOpenEntity selectByTypeAndOpenIdOrUnionId(String openType, String openId, String unionId) {
        return this.getOne(new LambdaQueryWrapper<WtUserOpenEntity>()
                .eq(WtUserOpenEntity::getOpenType, openType)
                .and(i -> i.eq(WtUserOpenEntity::getOpenId, openId).or()
                        .eq(WtUserOpenEntity::getUnionId, unionId)
                )
        );
    }

    @Override
    @Transactional
    public WtBaseResponse<WtOpenUserLoginResponse> wxLogin(String code) {
        try {
            /*获得微信信息*/
            WxMpUser wxMpUser = wxService.oauth2getUserInfo(wxService.oauth2getAccessToken(code), "en");
            /*获得已存储的微信信息*/
            WtUserOpenEntity entity = this.selectByTypeAndOpenIdOrUnionId(OPEN_TYPE_WECHAT, wxMpUser.getOpenId(), wxMpUser.getUnionId());

            String reponseToken = "";

            /*如果已存储微信信息，则生成TOKEN，并返回*/
            if (entity != null && entity.getUserId() != null) {
                reponseToken = wtUserService.createrToken(wtUserService.getById(entity.getUserId()));
            }
            saveWtWxOpenEneity(wxMpUser, entity);
            return new WtBaseResponse(new WtOpenUserLoginResponse(reponseToken, wxMpUser.getOpenId()));
        } catch (WxErrorException e) {
            log.warn("", e);
            throw WtExceptions.E_USER_OPEN_LOGIN;
        }
    }

    @Override
    public void bind(String openType, String openId, Long userId) {
        WtUserOpenEntity openEntity = this.selectByTypeAndOpenIdOrUnionId(openType, openId, "");
        if (null == openEntity) {
            throw WtExceptions.E_USER_OPEN_ID_NOEXIST;
        }
        if (null != openEntity.getUserId()) {
            throw WtExceptions.E_USER_OPEN_ID_BINDED;
        }
        openEntity.setUserId(userId);
        this.updateById(openEntity);
    }

    @Override
    public void unbind(String openType, String openId, Long userId) {
        WtUserOpenEntity openEntity = this.selectByTypeAndOpenIdOrUnionId(openType, openId, "");
        if (null == openEntity) {
            throw WtExceptions.E_USER_OPEN_ID_NOEXIST;
        }
        if (openEntity.getUserId() != userId) {
            throw WtExceptions.E_USER_OPEN_ID_BINDED;
        }
        openEntity.setUserId(null);
        this.updateById(openEntity);
    }

    @Override
    public WtBaseResponse<WtOpenUserLoginResponse> qqLogin(String code, String state) {
        try {
            String accessToken = qqoAuth.getAccessToken(code, state);
            if (null == accessToken) {
                throw WtExceptions.E_USER_OPEN_LOGIN;
            }
            log.debug("获得访问TOKEN {}",accessToken);

            String openID = qqoAuth.getOpenId(accessToken);
            if (null == openID) {
                throw WtExceptions.E_USER_OPEN_LOGIN;
            }

            log.debug("获得访问OPEN_ID {}",openID);

            String reponseToken = "";
            WtUserOpenEntity entity = selectByTypeAndOpenIdOrUnionId(OPEN_TYPE_QQ, openID, "qq");
            if (entity != null && entity.getUserId() != null) {
                reponseToken = wtUserService.createrToken(wtUserService.getById(entity.getUserId()));
            }

            UserInfoBean userInfo = qqoAuth.getUserInfo(openID, accessToken);

            log.debug("获取用户信息 {}",userInfo);
            if (userInfo != null) {
                saveWtQQOpenEneity(openID, userInfo, entity);
            }

            return new WtBaseResponse(new WtOpenUserLoginResponse(reponseToken, openID));
        } catch (Exception e) {
            log.debug("", e);
            throw WtExceptions.E_USER_OPEN_LOGIN;
        }
    }


    private void saveWtQQOpenEneity(String openId, UserInfoBean qqMpUser, WtUserOpenEntity entity) {
        WtUserOpenEntity saveEntity = entity == null ? new WtUserOpenEntity() : entity;

        /*如果是新用户填写创建时间*/
        if (null == entity) {
            saveEntity.setCreateTime(LocalDateTime.now());
        }

        if(qqMpUser != null) {
            saveEntity
                    .setHeadImg(qqMpUser.getAvatar().getAvatarURL100())
                    .setGender(qqMpUser.getGender())
                    .setNickname(qqMpUser.getNickname());
        }

        saveEntity.setOpenId(openId)
                .setUnionId("unkonw")
                .setUpdateTime(LocalDateTime.now())
                .setOpenType(OPEN_TYPE_QQ);

        this.saveOrUpdate(saveEntity);
    }

    private void saveWtWxOpenEneity(WxMpUser wxMpUser, WtUserOpenEntity entity) {
        WtUserOpenEntity saveEntity = entity == null ? new WtUserOpenEntity() : entity;

        /*如果是新用户填写创建时间*/
        if (null == entity) {
            saveEntity.setCreateTime(LocalDateTime.now());
        }

        saveEntity.setOpenId(wxMpUser.getOpenId())
                .setUnionId(wxMpUser.getUnionId())
                .setHeadImg(wxMpUser.getHeadImgUrl())
                .setCity(wxMpUser.getCity())
                .setProvince(wxMpUser.getProvince())
                .setCountry(wxMpUser.getCountry())
                .setGender(wxMpUser.getSexDesc())
                .setNickname(wxMpUser.getNickname())
                .setUpdateTime(LocalDateTime.now())
                .setOpenType(OPEN_TYPE_WECHAT);
        this.saveOrUpdate(saveEntity);
    }
}
